Unique's Blog

Java SE基础

2022-09-04 · 2741字 · 12 min read
🏷️  Java

https://www.acwing.com/blog/content/21860/

https://www.w3cschool.cn/java/

http://www.java2s.com

变量和输入输出

Java的所有变量和函数都要定义在class中。

与C++主要的区别:

  • Java属于完全面向对象语言,没有运算符重载(需要特定的方法实现功能)
  • 使用虚拟机解释运行

基础类型

8种内置数据类型/基础类型,不支持无符号整数类型

基础类型 字节数 举例
byte 1 123
short 2 12345
int 4 123456789
long 8 1234567891011L
float 4 1.2F
double 8 1.2,1.2D
boolean 1 true,false
char 2 'A','\u0041'

输出输出

输入

方式1 ,使用Scanner类输入,效率较低,输入规模较小时使用

Scanner sc = new Scanner(System.in);
String str = sc.next();  // 读入下一个字符串
int x = sc.nextInt();  // 读入下一个整数
float y = sc.nextFloat();  // 读入下一个单精度浮点数
double z = sc.nextDouble();  // 读入下一个双精度浮点数
String line = sc.nextLine();  // 读入下一行

方式2,使用输入流和缓存,效率较高,输入规模较大时使用。注意需要抛异常。

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str = br.readLine();
        System.out.println(str);
    }
}

输出

方式1,使用print系列方法,效率较低,输出规模较小时使用。

System.out.println(123);  // 输出整数 + 换行
System.out.println("Hello World");  // 输出字符串 + 换行
System.out.print(123);  // 输出整数
System.out.print("yxc\n");  // 输出字符串
System.out.printf("%04d %.2f\n", 4, 123.456D);  // 格式化输出,float与double都用%f输出

方式2,使用输出流和缓存效率较高,输出规模较大时使用。注意需要抛异常。

import java.io.BufferedWriter;
import java.io.OutputStreamWriter;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        bw.write("Hello World\n");
        bw.flush();  // 需要手动刷新缓冲区
    }
}

字符串和数组

字符串

字符串类String的常用初始化方式:

String a = "Hello World";
String b = "My name is";
String x = b;  // 存储到了相同地址
String c = b + "yxc";  // String可以通过+拼接
String d = "My age is " + 18;  // int会被隐式转化成字符串"18"
String str = String.format("My age is %d", 18);  // 格式化字符串,类似于C++中的sprintf
String money_str = "123.45";
double money = Double.parseDouble(money_str);  // String转double;其余包装类型具有类似方法

注意:Java 中的字符串是只读变量(底层使用 final 修饰),不能修改;每次拼接会构造一个新的字符串。

注意访问String中的字符方式:

  • str.length()返回该字符串 Unicode 码点数量(字符的数量)

  • 使用str.charAt(int index)访问第index个字符

说明:底层使用 char(16bit) 存储,UTF16编码思想:从U+D800U+DFFF之间的码位区段是永久保留不映射到Unicode字符。UTF-16就利用保留下来的0xD800-0xDFFF区段的码位来对**辅助平面的字符(从U+10000到U+10FFFF)**的码位进行编码。https://zh.m.wikipedia.org/zh-hans/UTF-16

String str = "Hello World";
for (int i = 0; i < str.length(); i ++ ) {
    System.out.print(str.charAt(i));  // 只能读取,不能写入
}

字符串类常用 API:

  • length():返回长度

  • split(String regex):分割字符串

  • indexOf(int c)indexOf(String str):查找,返回第一次找到下标,找不到返回-1

  • equals():判断两个字符串是否相等,注意不能直接用 ==

  • compareTo():判断两个字符串的字典序大小,负数表示小于,0表示相等,正数表示大于

  • startsWith():判断是否以某个前缀开头

  • endsWith():判断是否以某个后缀结尾

  • trim():去掉首尾的空白字符

  • toLowerCase():全部用小写字符

  • toUpperCase():全部用大写字符

  • replace(char oldChar, char newChar):替换字符(所有位置)

  • replace(CharSequence target, CharSequence rep):替换字符串(replaceFirst,replaceAll)

  • substring(int beginIndex, int endIndex):返回[beginIndex, endIndex)中的子串

可修改的字符串类型StringBuilderStringBuffer

如果打算修改字符串,可以使用StringBuilderStringBuffer

StringBuilder线程不安全,速度较快;而StringBuffer线程安全,速度较慢。

StringBuilder sb = new StringBuilder("Hello ");  // 初始化
sb.append("World");  // 拼接字符串
System.out.println(sb);

for (int i = 0; i < sb.length(); i ++ ) {
    sb.setCharAt(i, (char)(sb.charAt(i) + 1));  // 读取和写入字符
}

System.out.println(sb);

常用 API:

  • reverse():翻转字符串

数组

Java 数组是引用类型,推荐使用 Java风格int[] arr

初始化定长数组,长度可以是变量,并且可以在初始化时赋值

int[] a = new int[5];  // 初始化长度为5的int数组,初始值为0
int n = 10;
float[] b = new float[n];  // 初始化长度为n的float数组,初始值为0.0F
char[] c = {'a', 'b', 'c'};  // 初始化长度为3的char数组,初始值为:'a', 'b', 'c'
char[] d = c;  // d与c地址相同,更改c中的元素,d中的元素也会改变【引用类型】

多维数组

注意数组是引用类型,多维数组的变量也是引用类型,使用应该申请空间。

int[][] a = new int[2][3];
a[1][2] = 1;
int[][] b = {
        {1, 2, 3},
        {4, 5, 6},
}; // 声明和初始化赋值
System.out.println(a[1][2]);
System.out.println(b[0][1]);

数组常用 API:(使用Arrays工具类操作)

  • 属性 length:返回数组长度,注意不加小括号(属性)

  • Arrays.sort():数组排序

  • Arrays.fill(int[] a, int val):填充数组

  • Arrays.toString():将数组转化为字符串

  • Arrays.deepToString():将多维数组转化为字符串

  • Arrays.asList(T…)返回自己实现的一个内部类ArrayList(实现了List接口)—保存了参数数组的引用,是该数组的一个视图(修改会反映到原数组);说明:如果要得到一个可独立修改并可以添加/删除的List,使用***ArrayList<>(Arrays.asList(array))***

  • copyOf复制数组(一维);binarySearch()二分查找,需要先排序;equals()判断两个数组是否相等,如果元素是对象使用(e1==null ? e2==null : e1.equals(e2))判断对应位置元素相等;对于多维数组使用deepEquals()stream()返回对应元素的流;

  • 数组是不可变长度的

类和接口

Java 中所有变量和函数都要定义在类中

源文件声明规则

  • 一个源文件中最多只能有一个public类(其它类都为默认)

  • 源文件的名称应该和public类的类名保持一致

  • 每个源文件中,先写package语句,再写import语句,最后定义类


变量或方法前加static表示静态变量(类变量)/静态方法(类方法),属于class,而不属于class的具体实例。static 可以修饰 Block 即静态块,用来初始化静态数据成员。static也可用来修饰内部类。

  • 静态方法中只能调用静态方法和静态变量即类成员;

  • 静态方法不能使用this,super

内部类

内部类主要分为非静态内部类和静态内部类。

说明:非静态内部类,其对象总有一个隐式引用,指向了创建它的外部类对象,所以可以访问外部类变量/方法。可以定义 static变量但是不能定义静态块(java8)。

静态内部类,属于外部类本身,但是不属于外部类的任何对象

  • 静态内部类只能访问外部类的类成员

  • 外部类可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象访问其实例成员。

4种访问修饰符

Java 中有4中访问修饰符,public, protected, friendly(default), private

Java访问控制符的含义和可访问情况:

类内部 本包 子类 外部包
public ✔️ ✔️ ✔️ ✔️
protected ✔️ ✔️ ✔️ ✖️
friendly(default) ✔️ ✔️ ✖️ ✖️
private ✔️ ✖️ ✖️ ✖️
  • public:可以被所有其他类所访问

  • protected:自身,子类及同一个包中类可以访问

  • friendly:同一包中的类可以访问,声明时没有加修饰符,认为是friendly

  • private:只能被自己访问和修改

注意:Java的访问控制是停留在编译层的,也就是它不会在.class文件中留下任何的痕迹,只在编译的时候进行访问控制的检查。通过反射的手段,是可以访问任何包下任何类中的成员。

类继承

每个类最多只能继承一个类

示例:使用super来调用父类构造函数或者访问其成员。

class ColorPoint extends Point {
    private String color;

    public ColorPoint(int x, int y, String color) {
        super(x, y);
        this.color = color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String toString() {
        return String.format("(%d, %d, %s)", super.getX(), super.getY(), this.color);
    }
}

方法重载

方法签名不同,即参数个数或者对应类型不相同的同名函数称作方法重载。

类(及接口)的多态

父类引用(或者接口)可以指向不同子类(接口变量指向不同是的实现类对象),调用相同方法运行结果不同。【根据指向具体类型,调用其对应的方法实现】

接口和实现

接口主要用来定义行为,即定义类需要实现的方法(抽象方法的集合)。

接口可以继承其他多个接口,每个类可以实现多个接口(具有不同的行为)

  • 接口中可以定义(默认修饰符是public static final) 变量,以及抽象方法(默认使用public abstract修饰);可以定义方法的默认实现(方法前添加default关键字)。

  • 除非实现接口的类是抽象类,否则该类要定义/实现接口中的所有方法(默认方法可以不用);

  • 接口无法被实例化,但是可以被实现;

  • 接口类型可用来声明一个变量,可以是null,或是被绑定在实现接口的类对象。

🌈

标记接口:没有包含任何方法的接口,仅表明它的类属于一个特定的类型。作用在于向类添加数据类型(添加该接口类型)以及建立公共的父接口。

实例:

// 接口定义
interface Role {
    public void greet(); // public abstract
}
// 接口的继承,可以继承多个
interface Hero extends Role {
    public void attack();
}
// 接口的实现
class Zeus implements Hero {
    private final String name = "Zeus";
    public void attack() {
        System.out.println(name + ": attack!");
    }
    public void greet() {
        System.out.println(name + ": Hi!");
    }
}
// 接口的多态
class Athena implements Hero {
    private final String name = "Athena";
    public void attack() {
        System.out.println(name + ": attack!");
    }

    public void greet() {
        System.out.println(name + ": Hi!");
    }
}
// -------------------------------------------------
public class Main {
    public static void main(String[] args) {
        Hero[] heros = {new Zeus(), new Athena()};
        for (Hero hero: heros) {
            hero.greet();
        }
    }
}

泛型

Java的类和接口也可以定义泛型,即同一套函数可以作用于不同的对象类型。

注意Java 泛型只能使用对象类型,不能用于基本变量类型。并且只是编译期泛型,运行时会擦除。

其它

集合框架|泛型

IO

注解

反射

多线程

网络编程

XML

本文链接: Java SE基础

版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

发布日期: 2022-09-04

最新构建: 2024-12-26

本文已被阅读 0 次,该数据仅供参考

欢迎任何与文章内容相关并保持尊重的评论😊 !

共 43 篇文章 | Powered by Gridea | RSS
©2020-2024 Nuo. All rights reserved.